#include "mainwidget.h"
#include "ui_mainwidget.h"

MainWidget::MainWidget(QWidget *parent) :
	QWidget(parent),
	ui(new Ui::MainWidget)
{
	ui->setupUi(this);

	availableIcons << ":/icons/cool_sun.svg" <<
					  ":/icons/cool_sun-gray.svg";

	QString currentIconPath = getIconResourcePath();
	if (!availableIcons.contains(currentIconPath)) {
		availableIcons.prepend(currentIconPath);
	}

	iconFile.open();
	qDebug() << iconFile.fileName();
	trayIcon = new QSystemTrayIcon(this);
	connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
			this, SLOT(onTrayIconActivated(QSystemTrayIcon::ActivationReason)));
	trayIcon->installEventFilter(this);
	populateCmbIcons();
	updateOutputs();
	updateIcon();
	trayIcon->show();
	resize(sizeHint());
	hide();
}

MainWidget::~MainWidget()
{
	delete ui;
}

void MainWidget::populateCmbIcons()
{
	ui->cmbIcon->setUpdatesEnabled(false);
	ui->cmbIcon->clear();
	foreach (QString iconPath, availableIcons) {
		ui->cmbIcon->addItem(QIcon(iconPath), "", iconPath);
	}
	QString currentIconPath = getIconResourcePath();
	int index = qMax(0, availableIcons.indexOf(currentIconPath));
	ui->cmbIcon->setCurrentIndex(index);
	ui->cmbIcon->setUpdatesEnabled(true);
}

void MainWidget::changeEvent(QEvent* e)
{
	switch (e->type()) {
		case QEvent::LanguageChange: {
			this->ui->retranslateUi(this);
			break;
		}
		case QEvent::WindowStateChange: {
			if (this->windowState() & Qt::WindowMinimized) {
				QTimer::singleShot(50, this, SLOT(hide()));
			}
			break;
		}
		default:
			break;
	}
	QWidget::changeEvent(e);
}

void MainWidget::closeEvent(QCloseEvent *event)
{
	event->ignore();
	QTimer::singleShot(50, this, SLOT(hide()));
}

bool MainWidget::eventFilter(QObject *obj, QEvent *event)
{
	if (event->type() == QEvent::Wheel) {
		QWheelEvent *wheelEvent = dynamic_cast<QWheelEvent*>(event);
		if (wheelEvent) {
			int numDegrees = wheelEvent->delta() / 8;
			int numSteps = numDegrees / 15;
			onTrayIconWheel(numSteps);
			return true;
		}
	}
	return QObject::eventFilter(obj, event);
}

bool MainWidget::runCommand(QString program, QStringList arguments,
							QString &stdout, QString stderr)
{
	stdout.clear();
	stderr.clear();

	QProcess p;
	p.setProcessChannelMode(QProcess::SeparateChannels);
	p.start(program, arguments);
	if (!p.waitForStarted())
		return false;

	p.closeWriteChannel();

	if (!p.waitForFinished())
		return false;

	stdout = p.readAllStandardOutput();
	stderr = p.readAllStandardError();
	return p.exitCode() == 0;
}

bool MainWidget::runCommand(QString program, QStringList arguments)
{
	QString out, err;
	return runCommand(program, arguments, out, err);
}

void MainWidget::showNotification(QString title, QString text, int durationMs)
{
	if (!runCommand("notify-send",
					QStringList() <<
					"-i" << iconFile.fileName() <<
					"-u" << "normal" <<
					"-t" << QString("%1").arg(100 + durationMs) <<
					"-a" << "qbrightness" <<
					title << text)) {
		trayIcon->showMessage(title, text, QSystemTrayIcon::NoIcon, durationMs);
	}
}

void MainWidget::updateOutputs()
{
	QString out, err;
	runCommand("xrandr", QStringList() << "--verbose", out, err);
	QStringList lines = out.split('\n');

	activeOutputBrightness.clear();

	QString currentOutput;
	foreach (QString line, lines) {
		if (line.contains("connected")) {
			QString output = line.split(' ').first().trimmed();
			if (!output.isEmpty()) {
				currentOutput = output;
			} else {
				currentOutput.clear();
			}
		} else if (line.contains("*")) {
			if (!currentOutput.isEmpty()) {
				activeOutputBrightness[currentOutput] = 1.0;
			}
		}
	}

	currentOutput.clear();
	foreach (QString line, lines) {
		if (line.contains("connected")) {
			QString output = line.split(' ').first().trimmed();
			if (!output.isEmpty()) {
				currentOutput = output;
			} else {
				currentOutput.clear();
			}
		} else if (line.contains("Brightness:")) {
			if (!currentOutput.isEmpty()) {
				bool ok;
				qreal v = line.split("Brightness:").last().toDouble(&ok);
				if (ok) {
					activeOutputBrightness[currentOutput] = v;
				}
			}
		}
	}
}

void MainWidget::setBrightness()
{
	foreach (QString output, activeOutputBrightness.uniqueKeys()) {
		activeOutputBrightness[output] = qMin(1.0, activeOutputBrightness[output]);
		activeOutputBrightness[output] = qMax(0.1, activeOutputBrightness[output]);
		runCommand("xrandr",
				   QStringList() <<
				   "--output" << output <<
				   "--brightness" << QString("%1").arg(activeOutputBrightness[output]));
	}
	updateOutputs();
	showNotification("Brightness", getBrightnessMessage(), 1000);
	updateIcon();
}

void MainWidget::adjustBrightness(int numSteps)
{
	updateOutputs();
	foreach (QString output, activeOutputBrightness.uniqueKeys()) {
		activeOutputBrightness[output] += numSteps * 0.05;
	}
	setBrightness();
}

QString MainWidget::getBrightnessMessage()
{
	QString message;
	foreach (QString output, activeOutputBrightness.uniqueKeys()) {
		if (!message.isEmpty())
			message += "\n";
		message += QString("Output %1: %2")
				   .arg(output)
				   .arg(activeOutputBrightness[output], 0, 'f', 2);
	}
	return message;
}

void MainWidget::updateIcon()
{
	QString iconPath = getIconResourcePath();
	QFile resourceFile(iconPath);
	resourceFile.open(QFile::ReadOnly);
	QByteArray data = resourceFile.readAll();
	iconFile.seek(0);
	iconFile.resize(0);
	while (!data.isEmpty()) {
		qint64 count = iconFile.write(data);
		if (count < 0) {
			break;
		}
		data = data.mid(count);
	}
	iconFile.flush();
	trayIcon->setIcon(QIcon(iconPath));
	ui->cmbIcon->setUpdatesEnabled(false);
	ui->cmbIcon->setCurrentIndex(qMax(0, availableIcons.indexOf(iconPath)));
	ui->cmbIcon->setUpdatesEnabled(true);
	setWindowIcon(QIcon(iconPath));
	trayIcon->setToolTip(QString("Brightness:\n"
								 "%1\n"
								 "\n"
								 "Use the mouse wheel on the tray icon to change the display brightness.")
						 .arg(getBrightnessMessage()));
}

void MainWidget::onTrayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
	if (reason == QSystemTrayIcon::Trigger) {
		onTrayIconLeftClick();
	} else if (reason == QSystemTrayIcon::MiddleClick) {
		onTrayIconMiddleClick();
	} else if (reason == QSystemTrayIcon::Context) {
		onTrayIconRightClick();
	} else if (reason == QSystemTrayIcon::DoubleClick) {
		onTrayIconDoubleClick();
	} else {
		onTrayIconLeftClick();
	}
}

void MainWidget::onTrayIconLeftClick()
{
	setVisible(!isVisible());
}

void MainWidget::onTrayIconMiddleClick()
{
}

void MainWidget::onTrayIconRightClick()
{
	setVisible(!isVisible());
}

void MainWidget::onTrayIconDoubleClick()
{
}

void MainWidget::onTrayIconWheel(int numSteps)
{
	adjustBrightness(numSteps);
}

void MainWidget::on_btnDecreaseBrightness_clicked()
{
	adjustBrightness(-1);
}

void MainWidget::on_btnIncreaseBrightness_clicked()
{
	adjustBrightness(1);
}

QString MainWidget::getIconResourcePath()
{
	return settings.value("icon", availableIcons.first()).toString();
}

void MainWidget::setIconResourcePath(QString value)
{
	settings.setValue("icon", value);
	settings.sync();
}

void MainWidget::on_cmbIcon_currentIndexChanged(int index)
{
	if (index < 0 || index > availableIcons.count())
		return;
	if (!ui->cmbIcon->updatesEnabled())
		return;
	setIconResourcePath(availableIcons[index]);
	updateIcon();
}

void MainWidget::on_btnExit_clicked()
{
	qApp->quit();
}

